﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Specialized;
using System.Collections;
using System.Web.UI.HtmlControls;
using Doo.WebUI;
using Doo.DataClass;
using System.Web.Compilation;
using System.Reflection;
using Doo.Extension;

namespace Doo.ServerControls
{
    [ToolboxData("<{0}:ObjectEditor runat=server></{0}:ObjectEditor>")]
    public class ObjectEditor : DataBoundControl, INamingContainer, IBindableControl, ILinkControl
    {
        public ObjectEditor() { Properties = new List<ObjectProperty>(); }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        public List<ObjectProperty> Properties { get; set; }

        protected ObjectEditorItem table;

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            table = new ObjectEditorItem();
            Controls.Add(table);
        }

        public IOrderedDictionary DataKeys
        {
            get
            {
                IOrderedDictionary keys = ViewState["keys"] as IOrderedDictionary;
                if (keys == null)
                {
                    keys = new OrderedDictionary();
                    ViewState["keys"] = keys;
                }
                return keys;
            }
            protected set
            {
                ViewState["keys"] = value;
            }
        }

        protected override bool OnBubbleEvent(object source, EventArgs args)
        {
            if (args is CommandEventArgs)
            {
                CommandEventArgs CmdArgs = (CommandEventArgs)args;
                switch (CmdArgs.CommandName)
                {
                    case "Update":
                        this.Update();
                        return true;
                }
            }

            return base.OnBubbleEvent(source, args);
        }

        protected override void CreateChildControls()
        {
            //1.add head
            int i = 0;
            foreach (var f in Properties)
            {
                var row = new HtmlTableRow();
                table.Rows.Add(row);
                //1.header
                var headercell = new HtmlTableCell("th");
                headercell.InnerText = f.Title;
                row.Cells.Add(headercell);
                //2.control
                var controlcell = new HtmlTableCell();
                f.autoid = "__" + i++;
                f.InitializeCell(controlcell);
                row.Cells.Add(controlcell);
                //3.validator
                var vacell = new HtmlTableCell();
                if (!f.DisableValidate) f.InitializeValidator(vacell);
                row.Cells.Add(vacell);
            }
            if (RequiresDataBinding)
            {
                EnsureDataBound();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="dataBinding">Whether the method has been called from DataBind or not.</param>
        protected virtual void CreateChildControls(System.Collections.IEnumerable data, bool dataBinding)
        {
            EnsureChildControls();
            if (dataBinding)
            {
                table.DataBind();//Must do this
            }
        }

        private OrderedDictionary _boundFieldValues;

        public IOrderedDictionary BoundFieldValues
        {
            get
            {
                if (_boundFieldValues == null) _boundFieldValues = new OrderedDictionary();
                return _boundFieldValues;
            }
        }

        protected override void PerformDataBinding(System.Collections.IEnumerable data)
        {
            if (data == null) return;

            var enumerator = data.GetEnumerator();
            enumerator.MoveNext();
            table.dataItem = enumerator.Current;

            base.PerformDataBinding(data);

            TrackViewState();

            CreateChildControls(data, true);
            ChildControlsCreated = true;

            if (IsBoundUsingDataSourceID == true && IsViewStateEnabled)
            {
                //在这里获取Bind的Values
                int i = 0;
                foreach (var r in Properties)
                {
                    r.ExtractValuesFromCell(BoundFieldValues, table.Rows[i++].Cells[1]);
                }
            }

        }

        #region IBindableControl 成员

        public void ExtractValues(System.Collections.Specialized.IOrderedDictionary dictionary)
        {
            throw new NotImplementedException();
        }

        #endregion

        public void Update()
        {
            IOrderedDictionary oldvalues = BoundFieldValues;
            IOrderedDictionary newvalues = new OrderedDictionary();
            int i = 0;
            foreach (var r in Properties)
            {
                r.ExtractValuesFromCell(newvalues, table.Rows[i++].Cells[1]);
            }
            var view = this.GetData();
            view.Update(DataKeys, newvalues, oldvalues, HandleUpdateCallback);
        }


        private bool HandleUpdateCallback(int affectedRows, Exception ex)
        {

            if (this.ValueChanged != null) this.ValueChanged(this, EventArgs.Empty);

            return true;
        }

        public event EventHandler ValueChanged;

        public IOrderedDictionary Values
        {
            get
            {
                //获取键值,仍然没有要返回的
                return null;
            }
        }

        public void ParentValueChanged(Control parent, IOrderedDictionary values)
        {
            this.DataKeys = values;
            RequiresDataBinding = true;
        }

        public override void DataBind()
        {
            //set k
            DataClassSource s = GetDataSource() as DataClassSource;
            s.Keys = this.DataKeys;
            s.SelectByRecord = true;
            base.DataBind();
        }

        public void ChildValueChanged(Control child, IOrderedDictionary values)
        {
            //Do Nothing
        }
    }

    public class ObjectEditorItem : HtmlTable, IDataItemContainer
    {
        #region IDataItemContainer 成员

        internal object dataItem;

        object IDataItemContainer.DataItem
        {
            get { return dataItem; }
        }

        int IDataItemContainer.DataItemIndex
        {
            get { return 1; }
        }

        int IDataItemContainer.DisplayIndex
        {
            get { return 1; }
        }

        #endregion
    }

    public abstract class ObjectProperty
    {
        public abstract void ExtractValuesFromCell(IOrderedDictionary dictionary, HtmlTableCell cell);

        public abstract void InitializeCell(HtmlTableCell cell);

        public string Title { get; set; }

        internal string autoid;
        /// <summary>
        /// 用于编程
        /// </summary>
        public string ID { get; set; }
        public string ControlID
        {
            get
            {
                return string.IsNullOrEmpty(ID) ? autoid : ID;
            }
        }

        #region 验证相关

        /// <summary>
        /// 是否不需要验证
        /// </summary>
        public bool DisableValidate { get; set; }

        /// <summary>
        /// 是否必需
        /// </summary>
        public bool Require { get; set; }

        public bool NoValidateInit { get; set; }

        /// <summary>
        /// 验证规则
        /// </summary>
        public string ValidateRules { get; set; }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        public List<Validators.ValidatorItem> Validators { get; set; }

        private Validators.Validator _validator;
        public void InitializeValidator(HtmlTableCell cell)
        {
            _validator = new Validators.Validator();
            _validator.ControlToValidate = ControlID;
            _validator.ID = ControlID + "__va";
            _validator.Title = Title;
            cell.Controls.Add(_validator);
            _validator.items = new List<Validators.ValidatorItem>();
            if (Require)
            {
                _validator.items.Add(new Validators.RequireValidator());
                _validator.ValidateEmpty = true;
            }
            if (NoValidateInit)
            {
                _validator.NoValidateInit = true;
            }
            if (!string.IsNullOrEmpty(ValidateRules))
            {
                string[] rules = ValidateRules.Split(',');
                foreach (var r in rules)
                {
                    var it = new Validators.TemplateValidator { TemplateID = r };
                    _validator.items.Add(it);
                }
            }
            if (Validators != null && Validators.Count > 0)
            {
                _validator.items.AddRange(Validators);
            }
        }

        #endregion
    }

    public class StringProperty : ObjectProperty
    {
        private TextBox txt;

        public string DataField { get; set; }

        public override void InitializeCell(HtmlTableCell cell)
        {
            txt = new TextBox { ID = ControlID };
            txt.DataBinding += new EventHandler(this.OnDataBindField);
            cell.Controls.Add(txt);
        }

        protected virtual void OnDataBindField(object sender, EventArgs e)
        {
            txt.Text = "";
            object dataitem = DataBinder.GetDataItem(txt.NamingContainer);
            if (dataitem == null) return;
            object value = DataBinder.GetPropertyValue(dataitem, DataField);
            if (value != null) txt.Text = value.ToString();
        }

        public override void ExtractValuesFromCell(IOrderedDictionary dictionary, HtmlTableCell cell)
        {
            if (dictionary.Contains(DataField))
            {
                dictionary[DataField] = txt.Text;
            }
            else
            {
                dictionary.Add(DataField, txt.Text);
            }
        }
    }

    public class CheckProperty : ObjectProperty
    {
        public string DataField { get; set; }

        public string CheckedValue { get; set; }

        public string UnCheckedValue { get; set; }

        private CheckBox cb;

        public override void ExtractValuesFromCell(IOrderedDictionary dictionary, HtmlTableCell cell)
        {
            string value = cb.Checked ? CheckedValue : UnCheckedValue;
            dictionary.Add(DataField, value);
        }

        public override void InitializeCell(HtmlTableCell cell)
        {
            cb = new CheckBox { ID = ControlID };
            cb.DataBinding += new EventHandler(cb_DataBinding);
            cell.Controls.Add(cb);
        }

        void cb_DataBinding(object sender, EventArgs e)
        {
            cb.Checked = false;
            object dataitem = DataBinder.GetDataItem(cb.NamingContainer);
            if (dataitem == null) { return; }
            object value = DataBinder.GetPropertyValue(dataitem, DataField);
            if (value == null) return;
            if (value.ToString() == CheckedValue) { cb.Checked = true; }
        }
    }

    public class DropDownProperty : ObjectProperty
    {
        private DropDownListEx ddl;

        public DropDownProperty() { ddl = new DropDownListEx(); }

        public string TypeName { get { return ddl.TypeName; } set { ddl.TypeName = value; } }

        public string DataField { get; set; }

        public string MeaningField { get; set; }

        public string FilterString { get { return ddl.FilterString; } set { ddl.FilterString = value; } }

        public int Filter { get { return ddl.Filter; } set { ddl.Filter = value; } }

        public override void ExtractValuesFromCell(IOrderedDictionary dictionary, HtmlTableCell cell)
        {
            dictionary.Add(DataField, ddl.SelectedValue);
            if (!string.IsNullOrEmpty(MeaningField))
            {
                dictionary.Add(MeaningField, ddl.SelectedItem.Text);
            }
        }

        public override void InitializeCell(HtmlTableCell cell)
        {
            ddl.ID = ControlID;
            cell.Controls.Add(ddl);
            ddl.EnsureTypeLoaded();
            ddl.DataBinding += new EventHandler(ddl_DataBinding);
        }

        void ddl_DataBinding(object sender, EventArgs e)
        {
            object dataitem = DataBinder.GetDataItem(ddl.NamingContainer);
            if (dataitem == null) { return; }
            object value = DataBinder.GetPropertyValue(dataitem, DataField);
            if (value == null) return;
            ListItem item = ddl.Items.FindByValue(value.ToString());
            if (item != null) item.Selected = true;
        }
    }


    public class TemplateProperty : ObjectProperty
    {
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(IDataItemContainer), BindingDirection.TwoWay)]
        public ITemplate ItemTemplate { get; set; }

        public override void InitializeCell(HtmlTableCell cell)
        {
            cell.InnerText = string.Empty;
            ItemTemplate.InstantiateIn(cell);
        }

        public override void ExtractValuesFromCell(IOrderedDictionary dictionary, HtmlTableCell cell)
        {
            if (ItemTemplate == null) return;
            var values = (ItemTemplate as IBindableTemplate).ExtractValues(cell);
            foreach (DictionaryEntry entry in values)
            {
                if (dictionary.Contains(entry.Key))
                {
                    dictionary[entry.Key] = entry.Value;
                }
                else
                {
                    dictionary.Add(entry.Key, entry.Value);
                }
            }
        }
    }
}
